package com.wolf.client;

import com.wolf.annotation.WolfReference;
import com.wolf.config.ClientProperties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @auth: dylan
 * @Desc:
 * @Time: 2024/5/3
 */
public class WolfClientBeanProcessor implements ApplicationContextAware, BeanClassLoaderAware, BeanFactoryPostProcessor {


    private ApplicationContext context;

    private ClassLoader classLoader;

    private ClientProperties properties;

    private final ConcurrentHashMap<String,BeanDefinition> DEFINITION_MAP=new ConcurrentHashMap<>();

    public WolfClientBeanProcessor(ClientProperties properties) {
        this.properties = properties;
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context=context;
    }


    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader=classLoader;
    }

    //bean实例化之前,beanDefinition加载之后触发
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //
        //1.获取所有的beanDefinition 遍历beanDefinition看是否包含WolfReference注解
        for (String definitionName:beanFactory.getBeanDefinitionNames()){
            BeanDefinition definition = beanFactory.getBeanDefinition(definitionName);
            String beanClassName = definition.getBeanClassName();
            if(!StringUtils.isEmpty(beanClassName)){
                Class<?> clazz = ClassUtils.resolveClassName(beanClassName, this.classLoader);
                ReflectionUtils.doWithFields(clazz,this::expansionDynamicBean);
            }
        }
        BeanDefinitionRegistry registry= (BeanDefinitionRegistry) beanFactory;
        this.DEFINITION_MAP.forEach((beanName,definition)->{
            if(!context.containsBean(beanName)){
                registry.registerBeanDefinition(beanName,definition);
            }
        });

    }

    /**
     *  给增加了注解的BeanDefinition添加动态代理并保存到内存
     */
    private void expansionDynamicBean(Field field){
        //WolfReference annotation = AnnotationUtils.getAnnotation(field, WolfReference.class);
        if(field.isAnnotationPresent(WolfReference.class)){
            //构建一个工厂Bean
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(WolfDynamicFactoryBean.class);
            builder.setInitMethodName("init");
            builder.addPropertyValue("host",this.properties.getHost());
            builder.addPropertyValue("port",this.properties.getPort());
            builder.addPropertyValue("interfaceClass",field.getType());
            BeanDefinition beanDefinition = builder.getBeanDefinition();
            //将BeanDefinition和BeanName映射
            DEFINITION_MAP.put(field.getName(),beanDefinition);
        }
    }
}
